var mainmodel = require("../model/basemodel");
var validator = require("../validation/validator");
var dbConfig = require("../db_connection/dbConfig");
var connection = dbConfig.getConnection();

/*
 * Developers
 * Anthony D. Teoxon
 * Aldrin Buncasan
 * Raymond Bio
 * 
 * */

BaseController = function(){
}

BaseController.prototype.DEFAULT_WHERE = " 1 = 1 ";
BaseController.prototype.DEFAULT_VALUE = "";
BaseController.prototype.FORM_ENTRIES = Array();
BaseController.prototype.SEARCH_ENTRIES = Array();
BaseController.prototype.TABLE = "tablename";
BaseController.prototype.FORM_VIEW = "default-form";
BaseController.prototype.LIST_VIEW = "default-list";
BaseController.prototype.RECORDS_PER_PAGE = 20;
BaseController.prototype.CURRENT_PAGE_NO = 0;
BaseController.prototype.VALIDATION_RULES = "none";
BaseController.prototype.LIST_JOIN_TABLES = {}; //{TABLE : FIELD}
BaseController.prototype.LIST_JOIN_FIELDS = {}; //{TABLE : FIELD}
BaseController.prototype.FORM_JOIN_TABLES = {};
BaseController.prototype.REFERENCE_DATA = {};
BaseController.prototype.REFERENCE_DATA_LIST = {};
BaseController.prototype.PAGE = "";

BaseController.prototype.getConnection = function(){
	return connection;
}

BaseController.prototype.bindForm = function(req, res, isFormSubmission, isSearch){
	var ENTRIES = this.FORM_ENTRIES;
	var VALIDATION_RULES = this.VALIDATION_RULES;
	console.log("IS SEARCH --- > " + isSearch);
	if(isSearch){
		ENTRIES = this.SEARCH_ENTRIES;
		VALIDATION_RULES = "none";//no validation
    }

	var retrievedData = {};
    for(var formData in ENTRIES){
    	var field = ENTRIES[formData];
    	var value = req.param(field);
    	console.log(field + " VALUE IS--->>>> " + value);
    	if(!isSearch && isFormSubmission)//not searching and should be form submission
    		retrievedData = validator.validate(VALIDATION_RULES, retrievedData, field , value);
    	
    	if(typeof value !== "undefined" && value != null  ){
    		if(isSearch && value == ""){
    			
    		}else
    			retrievedData[field] = value;
    	}else{
    		//if(this.DEFAULT_VALUE != "")
    		if( !isSearch )
    			retrievedData[field] = this.DEFAULT_VALUE;
    	}
    }
    
    this.postBindForm(req, res, isFormSubmission, isSearch, retrievedData);
    
    /*
    if(!isSearch && isFormSubmission){
    	retrievedData = this.customValidation(retrievedData);
    }*/
//    formData["errors"]
    ///retrievedData["errors"] = "shoul not insert"
//    console.log("*****------>" + JSON.stringify(retrievedData));
    return retrievedData;
}

BaseController.prototype.postBindForm = function(req, res, isFormSubmission, isSearch, retrievedData){
	
}

BaseController.prototype.getMainmodel = function(){
	return this.mainmodel;
}

BaseController.prototype.setBasicData = function(req, data){
	  		data["modified_by"] = req.cookies.USER_ID;
	  		data["date_modified"] = new Date();
	  		data["archived"] = 1; //valid
  		return data;
  }

BaseController.prototype.customValidation = function(req, res, data){

	//data["errors"]['fieldname']//*if has error
	return data;
}

/*
	Additional Data needed in your view
*/
/*
BaseController.prototype.referenceData = function(req, res, data, callback){
	
	if(typeof callback === "undefined" ){
		return data;
	}else{
		//return callback();
	}
}
*/

//REFERENCE DATA
//custom implementation
BaseController.prototype.referenceData = function(req, res, data, callback){
	var referenceData = {};
	var listConfigCount = Object.keys(this.REFERENCE_DATA_LIST).length;
	
	referenceData = this.processReferenceData(data, referenceData, callback);
	
	if(listConfigCount > 0){//if there's configuration
			this.processReferenceDataList(req, data, referenceData, callback, 0);
	}else{
		callback(referenceData);
	}
 }

BaseController.prototype.processReferenceData = function(data, referenceData, callback){
	return referenceData;
}


//REFERENCE DATALIST
BaseController.prototype.processReferenceDataList = function(req, data, referenceData, callback, counter){
	var controller = this;
	//var connection = this.getConnection();//method from basecontroller
	var listConfigCount = Object.keys(controller.REFERENCE_DATA_LIST).length;
	if(listConfigCount > 0){//check if there's configuration
		var QUERY = controller.REFERENCE_DATA_LIST[counter].query;
		var NAME = controller.REFERENCE_DATA_LIST[counter].name;
		var APPEND_CLAUSE = controller.REFERENCE_DATA_LIST[counter].appendCustomWhereClause;
		
		if(APPEND_CLAUSE){
			var appendedQuery = this.appendConditionToWhereClauseForReferenceData(req, data, NAME);;
			if(appendedQuery != this.DEFAULT_WHERE){//meaning query was modified
				appendedQuery = " and " + appendedQuery;
			}
			QUERY += appendedQuery;
		}
		
		var query = connection.query(QUERY, function(err, rows){
			console.log("K=>" + query.sql);
			referenceData[NAME] = rows;
			if(counter == listConfigCount - 1){
				callback(referenceData);
				
			}else{
				counter = counter+1;
				referenceData = controller.processReferenceDataList(req, data, referenceData, callback, counter);//recursion
			}
		});
	}
	
}


BaseController.prototype.modifyQueryBasedOnRole = function(req, query){
	//var USER_ROLE = "manager";
	//HAS MANAGER ROLE
	var HAS_ADMIN_ROLE = true;
	var HAS_MANAGER_ROLE = true;
	var HAS_CASHIER_ROLE = true;
	if(HAS_ADMIN_ROLE){
		
	}else if(HAS_MANAGER_ROLE){
		
	}else if(HAS_CASHIER_ROLE){
		
	}
	return query;
}


//SEARCH
BaseController.prototype.preSearch = function(req, res, data){
	return data;
}


BaseController.prototype.getRecordLimitString = function(req){
	//var recordStart = this.CURRENT_PAGE_NO;
	var recordStart = 0;
	var recordString = " limit ";
	
	if(req.param("pageNo") != null && req.param("pageNo") != ""){
		recordStart = parseInt(req.param("pageNo"));
	}
	
	//this.CURRENT_PAGE_NO = recordStart;
	
	recordString = recordString + (this.RECORDS_PER_PAGE * recordStart) + " , " + this.RECORDS_PER_PAGE ;
	return recordString;
}

BaseController.prototype.validateResult = function(result){
	if(typeof result !== "undefined")
		return result;
	else
		return {};
}

BaseController.prototype.validateRecordCount = function(result){
	//recordCount : controller.validateRecordCount(rowCount),//rowsCount[0].recordCount
	if(typeof result !== "undefined" && typeof result[0]  !== "undefined" &&  result[0].recordCount  !== "undefined")
		return result[0].recordCount;
	else{
		return 0;
	}
}

BaseController.prototype.addJoinsQueries = function( isSearch ){
	var controller = this;
	var queryObj = {};
	var queryCount = "SELECT count(1) as recordCount from " + controller.TABLE;
	
	var JOIN_TABLES = controller.LIST_JOIN_TABLES;
	if( !isSearch ){ //not searching - Add/Edit/Update
		JOIN_TABLES = controller.FORM_JOIN_TABLES;
	}
	
	var joinTablesCount = Object.keys(JOIN_TABLES).length;
	var queryCount = "SELECT count(1) as recordCount ";
	var joins = " from " + controller.TABLE + " obj ";
	var query = " SELECT obj.* " + joins;
	if( joinTablesCount > 0){
		
		var selects = "";
		query = " select obj.*"
		for(var field_to_join in JOIN_TABLES){
			var joinData = JOIN_TABLES[field_to_join];//company_id
			
			var fieldToJoinTable = "id";
			
				if(typeof joinData.fieldToJoin !== "undefined" ){
					fieldToJoinTable = joinData.fieldToJoin;
				}
			
			    for(var col in joinData.fields){
			    	var joinTableField = joinData.fields[col];
			    	selects +=  " ," + joinData.table + "." + joinTableField + " as " +  joinData.table + "_" + joinTableField;
			    }
				joins +=  " "+ joinData.joinType +" join " + joinData.table  + " on obj." + field_to_join + " = " + joinData.table + "." + fieldToJoinTable;
			}
		query += selects + joins; //generated query
	}
	queryCount += joins; //query for counting the records
	
	queryObj.QUERY_STRING = query;
	queryObj.QUERY_STRING_COUNT = queryCount;
	console.log("JOIN TABLES COUNT " + joinTablesCount);
	console.log("GENERATED JOIN QUERY IS ---> " + query);
	return queryObj;
}



BaseController.prototype.search = function(req, res){
	//if needslogin || not logged in 
		//return 
	
	var controller = this; //workaround for conflict inside connection object
	var formData = controller.bindForm(req, res, ((req.method=='POST')) ,true);//check if post
	var queryCondition = {"obj.archived" : 1};
	
	var limitString = controller.getRecordLimitString( req);
	
	
	var searchUrlParams = "";
	var queryObj =  controller.addJoinsQueries(true);
	    //query could be modify if there's configured LIST_JOIN_TABLES
	var SEARCH_QUERY = queryObj.QUERY_STRING;
	var SEARCH_QUERY_COUNT = queryObj.QUERY_STRING_COUNT;
	
	var data = formData;//reserve form data
		data = controller.preSearch(req, res, data);
		
		var additionalConditionToQuery = this.appendConditionToWhereClause(req, data);
		console.log("--> " + JSON.stringify(data));
		var dataLength =  Object.keys(data).length
    	if(dataLength > 0){
    		    //build search query
    		    var searchQuery = "";
    		    var dataCounter = 0;
    		    searchUrlParams = "";
    		    for(var searchEntry in data){
    		    	var val = "";
    		    	if(typeof data[searchEntry] !== "undefined" ){
    		    		val = data[searchEntry];
    		    	}
    		    	
    		    	
    		    	var objString = "obj.";
    		    	
    		    	if(searchEntry.indexOf(".") != -1) {
    		    		objString = "";
    		    	}
    		    	//declare variable objString = ""obj.""
    		    	///if searchEntry contains "."
    		    		//objString = ""
    		    	//
    		    	//searchQuery +=  objString + searchEntry + " like '%" + data[searchEntry] + "%'";
    		    	
    		    	searchQuery +=  objString + searchEntry + " like '%" + data[searchEntry] + "%'";
    		    	searchUrlParams += searchEntry + "=" +  data[searchEntry] + "&";
    		    	if(dataLength > 1 && dataCounter < dataLength-1)
    		    		searchQuery += " or ";
    		    	dataCounter++;
    		    }
    		    
		        var query = connection.query(SEARCH_QUERY + " WHERE (" + searchQuery + ") and " + additionalConditionToQuery + " " + limitString ,[ queryCondition], function(err, rows)
			        {
		        	console.log("FIRST - > " + query.sql);
				          if (err){
				              console.log("Error searching : %s ",err );
				          }else{
				          		data = controller.postSearch(req, res, data);
				          }
				         
				          var viewFunction = function(referenceData){
				        	  referenceData["searchUrlParams"] = searchUrlParams;
					       var query2=   connection.query(SEARCH_QUERY_COUNT + " WHERE (" + searchQuery + ")  and " + additionalConditionToQuery  ,[ queryCondition], function(err, rowsCount)
						        {
					    	   
					    	   	  console.log("SECOND - > " + query2.sql)
						          res.render(controller.LIST_VIEW, {
						          		action: "search", 
						          		controller : controller.CONTROLLER,
						          		page : controller.PAGE,
						          		title: "The Net - " + controller.TABLE + " List",
						          		contentHeader: controller.CONTROLLER + " List",
						          		record : data,
						          		records : controller.validateResult(rows),
						          		currentPage : controller.CURRENT_PAGE_NO,
						          		recordCount : controller.validateRecordCount(rowsCount),//rowsCount[0].recordCount
						          		recordsPerPage: controller.RECORDS_PER_PAGE,
						          		refData: referenceData
						          		
						          });
						        });
				          }
				          
				          controller.referenceData(req, res, data, viewFunction);
			      	});
	      }else{
		      	var query = connection.query(SEARCH_QUERY + " where ? and " + additionalConditionToQuery + " " + limitString,  queryCondition , function(err, rows)
			        {
				          if (err){
				              console.log("Error searching : %s ",err );
				          }else{
				          		data = controller.postSearch(req, res, data);
				          }
				          console.log("QUERY : " + query.sql);
				          var viewFunction = function(referenceData){
					          connection.query(SEARCH_QUERY_COUNT + " where ? and " + additionalConditionToQuery , [queryCondition], function(err, rowsCount)
						        {
					        	  referenceData["searchUrlParams"] = "";
					        	  console.log("controller.LIST_VIEW -- > " + controller.LIST_VIEW);
						          res.render(controller.LIST_VIEW, {
						          		action: "search", 
						          		controller : controller.CONTROLLER,
						          		page : controller.PAGE,
						          		title: "The Net - " + controller.TABLE + " List",
						          		contentHeader: controller.CONTROLLER + " List" ,
						          		userType : "UserType",
						          		record : data,
						          		records : controller.validateResult(rows) ,
						          		searchField : controller.SEARCH_ENTRIES ,
						          		currentPage : controller.CURRENT_PAGE_NO,
						          		recordCount : controller.validateRecordCount(rowsCount),//rowsCount[0].recordCount
						          		recordsPerPage: controller.RECORDS_PER_PAGE,
						          		refData: referenceData
						          		
						          });
						        });
					         
				          };
				          //              function(req, res, data, callback){
				          controller.referenceData(req, res, data, viewFunction);
			      	});
	      }

}

BaseController.prototype.postSearch = function(req, res, data){
	return data;
}


BaseController.prototype.setSearchParameters =function(){
	
}


//INSERT
BaseController.prototype.preInsert = function(req, res, data){
	return data;
}


BaseController.prototype.insert = function(req, res, isFormSubmission){
	console.log("IS FORM SUBMISSION? " + isFormSubmission);

	var controller = this; //workaround for conflict inside connection object
	var formData = controller.bindForm(req, res, isFormSubmission,  false);
	var codeId = "";//no code id
	var row = [];
		row[0] = formData;

	var data = formData;//reserve form data;
		if(isFormSubmission && !validator.hasError(formData)){
			data = controller.preInsert(req, res, data);
			var newData = data;//dont modify old data
  			newData = controller.setBasicData(req, newData);
  			newData['added_by'] = req.cookies.USER_ID;;
  			newData['date_added'] = new Date();
	        var query = connection.query("INSERT INTO " + controller.TABLE + " set ? ", [newData], function(err, rows)
	        {
	          if (err){
	              console.log("Error inserting : %s ",err );
	          }else{
	          	   data = controller.postInsert(req, res, data, rows);
	          }
	          
	          
	          //res.render(controller.FORM_VIEW, {action: "add",  title: "ADD PAGE FOR " + controller.TABLE  , refData: data} );
	          var viewFunction = function(referenceData){
		          //res.render(controller.FORM_VIEW, {
		          res.json({
	          	  		action: "add", 
		          		controller : controller.CONTROLLER,
		          		page : controller.PAGE,
		          		title: "The Net - Add " + controller.CONTROLLER,
		          		contentHeader: "Add " + controller.CONTROLLER,
		          		userType : "UserType",
		          		record : newData,
		          		id: codeId
		          		//refData: referenceData
	          	  } );
		          controller.logEvent("add",controller, rows);
	          }
	          
	          controller.referenceData(req, res, data, viewFunction);

	      	});
		}else{
			 //var referenceData =  controller.referenceData(req, res, data);
			 console.log("REFERENCE DATA RETURNED!!!!");
			 // res.render(controller.FORM_VIEW, {action: "add",  title: "ADD PAGE FOR " + controller.TABLE  , refData: {}} );

			 if(isFormSubmission){//WITH ERRORS
				 //////////////////////////
				 res.json( {
					      action: "add", 
			              controller : controller.CONTROLLER,
			              page : controller.PAGE,
			          	  record : controller.validateResult(row[0]),
			          	  id: codeId
		          	  });
				 //{}
			 }else{
				 var viewFunction = function(referenceData){
					    res.render(controller.FORM_VIEW, {
						 	action: "add", 
				          		controller : controller.CONTROLLER,
				          		page : controller.PAGE,
				          		title: "The Net - Add " + controller.CONTROLLER,
				          		contentHeader: "Add " + controller.CONTROLLER,
				          		userType : "UserType",
				          		record : controller.validateResult(row[0]),
				          		id: codeId,
				          		refData: referenceData
			          	  });
					 }
			     controller.referenceData(req, res, data, viewFunction);
			 }
		}
}

BaseController.prototype.postInsert = function(req, res, data, rows){
	return data;
}

//UPDATE
BaseController.prototype.preUpdate = function(req, res, data){
	return data;
}

BaseController.prototype.update = function(req, res, isFormSubmission){
	var controller = this; //workaround for conflict inside connection object
	var data = controller.bindForm(req, res , isFormSubmission , false);
	var codeId = req.param("id");
	var additionalConditionToQuery = this.appendConditionToWhereClause(req, data);
	var queryCondition = {archived : 1, id: codeId};
		if(isFormSubmission && !validator.hasError(data)){//save update
			data = controller.preUpdate(req, res, data);
			var newData = data;//dont modify old data
	  			newData = controller.setBasicData(req, newData);
	        var query = connection.query("UPDATE " + controller.TABLE + " set ? WHERE id = " + codeId + " and  archived = 1 and " + additionalConditionToQuery ,[data], function(err, row)
	        {
	          if (err){
	              console.log("Error updating : %s ",err );
	          }else{
	          	  data = controller.postUpdate(req, res, data);
	          }
			  //data = controller.referenceData(req, res, data);
			  controller.logEvent("update",controller, row);
			  //res.redirect("/" + controller.CONTROLLER + "/edit/" + codeId );
			  console.log("UUUUUUU--->" + req.originalUrl);
			  //res.redirect(req.originalUrl);
	          var viewFunction = function(referenceData){
		          //res.render(controller.FORM_VIEW, {
		          res.json({
	          	  		action: "edit", 
		          		controller : controller.CONTROLLER,
		          		page : controller.PAGE,
		          		contentHeader: "Edit " + controller.CONTROLLER,
		          		userType : "UserType",
		          		record : controller.validateResult(newData),
		          		id: codeId
	          	  } );
		         // controller.logEvent("edit",controller, rows);
	          }
	          
	          controller.referenceData(req, res, data, viewFunction);

	      	});
	    }else{
	    	var queryObj =  controller.addJoinsQueries(false);
	        //query could be modify if there's configured LIST_JOIN_TABLES
	    	var QUERY = queryObj.QUERY_STRING;
	    	//var QUERY_COUNT = queryObj.QUERY_STRING_COUNT;
	   		var query = connection.query(QUERY +" where obj.id = ? and " + additionalConditionToQuery +" limit 1",[codeId], function(err, row)
	        {
	          if (err){
	              console.log("Error retrieving : %s ",err );
	          }else{
	        	  
	 			 if(isFormSubmission){//WITH ERRORS
					 //////////////////////////
					 res.json( {
						      action: "edit", 
				              controller : controller.CONTROLLER,
				              page : controller.PAGE,
				          	  record : row[0],
				          	  id: codeId
			          	  });
					 //{}
				 }else{
	        	  
		        	  var viewFunction = function(referenceData){
			        	  var editData = row[0];
			          	  res.render(controller.FORM_VIEW, {
			          	  		action: "edit", 
				          		controller : controller.CONTROLLER,
				          		page : controller.PAGE,
				          		title: "The Net - " + controller.CONTROLLER + " Edit",
				          		contentHeader: "Edit " + controller.CONTROLLER,
				          		userType : "UserType",
				          		record : controller.validateResult(editData),
				          		id: codeId,
				          		refData: referenceData
			          	  } );
		        	  }
		        	  controller.referenceData(req, res, data, viewFunction);
				 }
	          }
	      	});
	    }
}

BaseController.prototype.postUpdate = function(req, res, data){
	return data;
}

//DELETE
BaseController.prototype.preDelete = function(req, res, data){
	return data;
}


BaseController.prototype.delete = function(req, res){

	//var data = this.bindForm(req, res);
	var controller = this; //workaround for conflict inside connection object
	var data = {};
	    codeId = req.param("id");
		data = controller.preDelete(req, res, data);
		data["archived"] = 0;
		var additionalConditionToQuery = this.appendConditionToWhereClause(req, data);

        var query = connection.query("UPDATE " + controller.TABLE + " set ? WHERE id = ? and " + additionalConditionToQuery,[data, codeId], function(err, rows)
        {
	          if (err){
	              console.log("Error deleting : %s ",err );
	          }else{
	            	data = controller.postDelete(req, res, data);
	          }
	          controller.search(req, res);
	          controller.logEvent("deleted",controller, rows);
	          //res.redirect("/" + controller.CONTROLLER );
	          //res.redirect("/" + req.originalUrl);
      	});
}

BaseController.prototype.postDelete = function(req, res, data){
	return data;
}

BaseController.prototype.logEvent = function(action ,controller, object){
	//LOG MESSAGE HERE
	//console.log(action + " ================ |" + controller.TABLE + " | ======================= " + JSON.stringify(object));
}

/*
BaseController.prototype.appendConditionToWhereClause = function(req, data){
	return this.DEFAULT_WHERE;//additional condition
}*/


BaseController.prototype.appendConditionToWhereClauseForReferenceData = function(req, data, name){
	var groupId = req.cookies.USER_GROUP_ID;
	if(name == "branchList" || name == "transactionSummary"){
		if(HAS_ROLE(groupId,'has_admin_role')){
			return "1 = 1";
		}
		else if(HAS_ROLE(groupId,'has_manager_role')){
			return "branch_id = " + req.cookies.BRANCH_ID;
		}else if(HAS_ROLE(groupId,'has_cashier_role')){
			return "branch_id = " + req.cookies.BRANCH_ID + " and (obj.added_by = " + req.cookies.USER_ID+")";
		}else{
			return " 1!=1"
		}
	}
	
	
	if(name == "companyList" || name == "transactionSummary"){
		if(HAS_ROLE(groupId,'has_admin_role')){
			return "1 = 1";
		}
		else if(HAS_ROLE(groupId,'has_manager_role')){
			return "branch_id = " + req.cookies.BRANCH_ID;
		}else if(HAS_ROLE(groupId,'has_cashier_role')){
			return "branch_id = " + req.cookies.BRANCH_ID + " and (obj.added_by = " + req.cookies.USER_ID+")";
		}else{
			return " 1!=1"
		}
	}
	
	if(name == "userGroupList"){
		if(HAS_ROLE(groupId,'has_admin_role')){
			return "1 = 1";
		}
		else if(HAS_ROLE(groupId,'has_manager_role')){
			return "name = 'Cashier' or name = 'Manager'";
		}else if(HAS_ROLE(groupId,'has_cashier_role')){
			return "id = " + req.cookies.BRANCH_ID + " and (obj.added_by = " + req.cookies.USER_ID+")";
		}else{
			return " 1!=1"
		}
	}
	
	return this.DEFAULT_WHERE;
}

BaseController.prototype.appendConditionToWhereClause = function(req, data){

	var groupId = req.cookies.USER_GROUP_ID;
	if(HAS_ROLE(groupId,'has_admin_role')){
		return "1 = 1";
	}
	else if(HAS_ROLE(groupId,'has_manager_role')){
		return "obj.branch_id = " + req.cookies.BRANCH_ID;
	}else if(HAS_ROLE(groupId,'has_cashier_role')){
		return "obj.branch_id = " + req.cookies.BRANCH_ID + " and (obj.added_by = " + req.cookies.USER_ID+")";
	}else{
		return " 1!=1"
	}
}



module.exports =  BaseController;